Canvas 2D
Canvas2D is an optional package used to bridge HTML Canvas API with Wolfram Language allowing low-level raster realtime render.
Setting up
Firstly, you need to load this package into any context except Global:
Needs["Canvas2D`"->"ctx`"];
To create canvas context use the following constructor:
context = ctx`Canvas2D[]
Then to display and render graphics in the given context - provide Image:
Image[context, ImageResolution->{300,300}]
Draw basic shapes
Created context is used to pipe commands to Canvas API (and then internally to GPU). Let's make basic shapes:
ctx`BeginPath[context];
ctx`MoveTo[context, {25, 25}];
ctx`LineTo[context, {105, 25}];
ctx`LineTo[context, {25, 105}];
ctx`Fill[context];
ctx`BeginPath[context];
ctx`MoveTo[context, {125, 125}];
ctx`LineTo[context, {125, 45}];
ctx`LineTo[context, {45, 125}];
ctx`ClosePath[context];
ctx`Stroke[context];
(* Send the buffer of commands *)
ctx`Dispatch[context];
API allows to make gradients and change filling colors as well:
(* top-left quarter *)
ctx`SetFillStyle[context, "#FD0"];
ctx`FillRect[context, {0, 0}, 2{75, 75}];
(* top-right quarter *)
ctx`SetFillStyle[context, "#6C0"];
ctx`FillRect[context, 2{75, 0}, 2{75, 75}];
(* bottom-left quarter *)
ctx`SetFillStyle[context, "#09F"];
ctx`FillRect[context, 2{0, 75}, 2{75, 75}];
(* bottom-right quarter *)
ctx`SetFillStyle[context, "#F30"];
ctx`FillRect[context, 2{75, 75}, 2{75, 75}];
ctx`SetFillStyle[context, "#FFF"];
ctx`SetGlobalAlpha[context, 0.2];
Do[
  ctx`BeginPath[context];
  ctx`Arc[context, 2{75, 75}, 2 10 + 2 10 i, 0, 2.0 π];
  ctx`Fill[context];
, {i, 0, 6}];
ctx`Dispatch[context];

Animation
Passing Image to EventHandler expression allows to capture user events: for example mouse tracking feature.
AnimationFrameListener is also extended to work with canvas context symbols, i.e:
AnimationFrameListener[context_, "Event"->event_String]
Let's make some complex animations!
Handler generator function
SetAttributes[handler, HoldRest]
handler[c_, tcursor_, {width_ height_}] := Module[
  {
  w = width, h = height,               (* initial canvas size *)
  n = 101,    
  cursor = tcursor,
  (* number of particles *)
  rotSpeed = 0.02,                  (* angular velocity *)
  particles,
  theta, rad, col, old
  },
  
  (* center point *)
  cx = w/2;
  cy = h/2;
  
  (* semi-transparent drawing *)
  ctx`SetGlobalAlpha[c, 0.5];
  
  (* initialize particles: random angle, radius, colour *)
 particles = Table[
   {
    RandomReal[{0, 2 π}], 
    RandomReal[{0, 150}], 
    ctx`ColorToString[RandomColor[]],
    cursor
   },
   {n}
 ];
  Function[Null,
      cursor = cursor + 0.1 (tcursor - cursor);
      
      ctx`SetFillStyle[c, {Black, Opacity[0.05]}];
      ctx`FillRect[c, {0, 0}, {w, h}];
      
      (* draw each particle: from last cursor pos to new one *)
      Do[
        particles[[i, 1]] += rotSpeed;
        {theta, rad, col, old} = particles[[i]];
        Module[{newPos},
          newPos = cursor + {Cos[theta], Sin[theta]} rad;
          
          ctx`BeginPath[c];
          ctx`SetLineWidth[c, 4];
          ctx`SetStrokeStyle[c, col];
          ctx`MoveTo[c, old];
          ctx`LineTo[c, newPos];
          ctx`Stroke[c];
          particles[[i,4]] = newPos; 
        ],
        {i, n}
      ];
      ctx`Dispatch[c];
  ]
]
aContext = ctx`Canvas2D[];
tcursor = {250,250};
EventHandler["frame", handler[aContext, tcursor, {500,500}]];
  EventHandler[
    Image[aContext, ImageResolution->{500,500}, Epilog->{
      AnimationFrameListener[aContext, "Event"->"frame"]
    }], {
      "mousemove" -> Function[xy, 
        tcursor = {xy[[1]], xy[[2]]}
      ]
  }
]
